package com.ruoyi.mes.service.impl;

import java.util.Comparator;
import java.util.List;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.mes.domain.*;
import com.ruoyi.mes.mapper.*;
import com.ruoyi.mes.utils.CodeUtils;
import com.ruoyi.mes.vo.plan.ReleaseVo;
import com.ruoyi.mes.vo.product.BomMtrVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.mes.service.IProgPlanDetailService;
import org.springframework.transaction.annotation.Transactional;

import static com.ruoyi.common.core.domain.AjaxResult.DATA_TAG;

/**
 * 生产计划下达明细Service业务层处理
 *
 * @author LongAndHao
 * @date 2023-05-09
 */
@Service
public class ProgPlanDetailServiceImpl implements IProgPlanDetailService {
    @Autowired
    private WkspTaskMapper wkspTaskMapper;

    @Autowired
    private WkspTaskServiceImpl wkspTaskService;

    @Autowired
    private BuyNeedMapper buyNeedMapper;

    @Autowired
    private MtrStockMapper mtrStockMapper;

    @Autowired
    private ProgPlanMapper progPlanMapper;

    @Autowired
    private ProInfoServiceImpl proInfoService;

    @Autowired
    private MtrPlanServiceImpl mtrPlanService;

    @Autowired
    private ProgPlanDetailMapper progPlanDetailMapper;

    @Autowired
    private TaskCartMapper taskCartMapper;

    @Autowired
    private PickInfoMapper pickInfoMapper;

    @Autowired
    private RevokePickServiceImpl revokePickService;





    /**
     * 查询生产计划下达明细
     *
     * @param id 生产计划下达明细主键
     * @return 生产计划下达明细
     */
    @Override
    public ProgPlanDetail selectProgPlanDetailById(Long id) {
        return progPlanDetailMapper.selectProgPlanDetailById(id);
    }

    /**
     * 查询生产计划下达明细列表
     *
     * @param progPlanDetail 生产计划下达明细
     * @return 生产计划下达明细
     */
    @Override
    public List<ProgPlanDetail> selectProgPlanDetailList(ProgPlanDetail progPlanDetail) {
        return progPlanDetailMapper.selectProgPlanDetailList(progPlanDetail);
    }

    /**
     * 新增生产计划下达明细
     *
     * @param progPlanDetail 生产计划下达明细
     * @return 结果
     */
    @Override
    public int insertProgPlanDetail(ProgPlanDetail progPlanDetail) {
        progPlanDetail.setCreateTime(DateUtils.getNowDate());
        return progPlanDetailMapper.insertProgPlanDetail(progPlanDetail);
    }

    /**
     * 修改生产计划下达明细
     *
     * @param progPlanDetail 生产计划下达明细
     * @return 结果
     */
    @Override
    public int updateProgPlanDetail(ProgPlanDetail progPlanDetail) {
        progPlanDetail.setUpdateTime(DateUtils.getNowDate());
        return progPlanDetailMapper.updateProgPlanDetail(progPlanDetail);
    }

    /**
     * 批量删除生产计划下达明细
     *
     * @param ids 需要删除的生产计划下达明细主键
     * @return 结果
     */
    @Override
    public int deleteProgPlanDetailByIds(Long[] ids) {
        return progPlanDetailMapper.deleteProgPlanDetailByIds(ids);
    }

    /**
     * 删除生产计划下达明细信息
     *
     * @param id 生产计划下达明细主键
     * @return 结果
     */
    @Override
    public int deleteProgPlanDetailById(Long id) {
        return progPlanDetailMapper.deleteProgPlanDetailById(id);
    }


    /**
     * 计划下达 - 生成物料计划车间任务等
     *
     * @param releaseVo
     * @return
     */
    @Override
    public AjaxResult release(ReleaseVo releaseVo) {
        //更新生产计划状态
        ProgPlan progPlan = progPlanMapper.selectProgPlanById(releaseVo.getId());
        progPlan.setStatus(1L);
        progPlanMapper.updateProgPlan(progPlan);

        //插入下达明细
        ProgPlanDetail progPlanDetail = new ProgPlanDetail();
        progPlanDetail.setProgId(releaseVo.getId());
        progPlanDetail.setStartTime(releaseVo.getStartTime());
        progPlanDetail.setOverTime(releaseVo.getOverTime());
        progPlanDetail.setStatus(1L);//下达后更新状态
        progPlanDetail.setReleaseQuantity(releaseVo.getReleaseQuantity());
        progPlanDetailMapper.insertProgPlanDetail(progPlanDetail);

        //生成物料计划
        ProInfo proInfo = proInfoService.selectProInfoById(progPlan.getProId());
        String mtrPlanCode = CodeUtils.MtrPlanCodeCreat();//生成物料计划编码
        String buyNeedCode = CodeUtils.BuyNeedCodeCreat(); //生成采购需求编码
        R<BomMtrVo> BomMtrVo = proInfoService.getBomAndMtrByProId(proInfo.getId());
        List<MtrInfo> mtrs = BomMtrVo.getData().getMtrs();//获取产品对应的Bom物料
        for (MtrInfo mtr : mtrs) {
            MtrPlan mtrPlan = new MtrPlan();
            BeanUtils.copyProperties(mtr, mtrPlan);
            mtrPlan.setMtrQuantity(mtr.getMtrQuantity() * releaseVo.getReleaseQuantity());
            mtrPlan.setMtrCode(mtr.getMtrCode());
            mtrPlan.setProgDetailId(progPlanDetail.getId());
            mtrPlan.setCode(mtrPlanCode);
            mtrPlan.setStatus(0L);//默认未生成

            //判断库存物料是否充足，不充足直接根据物料计划生成采购需求 需改动默认状态
            List<MtrStock> stocks = mtrStockMapper.selectMtrStockByMtrCode(mtr.getMtrCode());
            if (stocks.size() !=0){
                MtrStock mtrStock = stocks.stream().max(Comparator.comparing(MtrStock::getMtrQuantity)).get();

                if (mtrPlan.getMtrQuantity() > mtrStock.getMtrQuantity()) {
                    BuyNeed buyNeed = new BuyNeed();
                    buyNeed.setNeedCode(buyNeedCode);
                    buyNeed.setProgId(releaseVo.getId());
                    buyNeed.setMtrCode(mtr.getMtrCode());
                    buyNeed.setMtrName(mtr.getMtrName());
                    buyNeed.setMtrPlanCode(mtrPlanCode);
                    buyNeed.setRemark("测试数据");

                    buyNeed.setNeedQuantity(mtrPlan.getMtrQuantity() - mtrStock.getMtrQuantity());
                    buyNeed.setStatus(0L);//默认未采购
                    buyNeedMapper.insertBuyNeed(buyNeed);
                    mtrPlan.setStatus(1L);//物料计划已生成
                }

            }else {//若缺少库存物料则直接生成采购需求
                BuyNeed buyNeed = new BuyNeed();
                buyNeed.setNeedCode(buyNeedCode);
                buyNeed.setProgId(releaseVo.getId());
                buyNeed.setMtrCode(mtr.getMtrCode());
                buyNeed.setMtrName(mtr.getMtrName());
                buyNeed.setMtrPlanCode(mtrPlanCode);
                buyNeed.setRemark("测试数据");

                buyNeed.setNeedQuantity(mtrPlan.getMtrQuantity());
                buyNeed.setStatus(0L);//默认未采购
                buyNeedMapper.insertBuyNeed(buyNeed);

                mtrPlan.setStatus(1L);//物料计划已生成
            }
            mtrPlanService.insertMtrPlan(mtrPlan);
        }

        //生成车间任务
        WkspTask wkspTask = new WkspTask();
        wkspTask.setProgDetailId(progPlanDetail.getId());
        wkspTask.setProId(progPlan.getProId());
        wkspTask.setWkspCode(CodeUtils.WkspCodeCreat());
        wkspTask.setWkspPlanQuantity(releaseVo.getReleaseQuantity());
        wkspTask.setWkspReadyQuantity(0L);//默认已生产0个
        wkspTask.setStartTime(releaseVo.getStartTime());
        wkspTask.setOverTime(releaseVo.getOverTime());
        wkspTask.setOperationStatus(0L);//默认未开工
        wkspTask.setPickingStatus(0L);//默认未申请领料
        wkspTask.setRemark("测试数据");
        wkspTaskMapper.insertWkspTask(wkspTask);

        return AjaxResult.success("下达成功!");
    }


    /**
     * 查 - 计划下达 -生产计划相同数据
     *
     * @param progId 生产计划id
     * @return
     */
    @Override
    public List<ProgPlanDetail> getList(Long progId) {
        return progPlanDetailMapper.getList(progId);
    }

    /**
     * 撤回 - 生产计划 - 车间任务及物料等
     *
     * @param id 生产计划明细id
     * @return
     */
    @Override
    @Transactional
    public AjaxResult revokeProgPlanDetails(Long id) {
        //撤回后更新状态为 已关闭
        ProgPlanDetail progPlanDetail = progPlanDetailMapper.selectProgPlanDetailById(id);
        progPlanDetail.setStatus(0L);
        progPlanDetailMapper.updateProgPlanDetail(progPlanDetail);

        //撤回物料计划和采购需求
        List<MtrPlan> mtrPlans = mtrPlanService.getMtrPlanByProgId(id);
        if (mtrPlans.size() != 0){
            mtrPlanService.revokePlanAndNeed(mtrPlans.get(0).getId());
        }

        //撤回车间任务、车间任务卡
        //数据准备
        WkspTask wkspTask = wkspTaskMapper.selectWkspTaskByProgDetailId(id);//车间任务
        boolean isRpt = false;//任务卡是否已报工标志 false- 未报工 true - 已报工
        List<TaskCart> taskCarts = taskCartMapper.selectTaskCartByWskpTaskId(wkspTask.getId());
        if (taskCarts.size() != 0){//已有任务卡,判断是否有报工
            //任务卡是否已有报工： 报工次数
            for (TaskCart taskCart : taskCarts) {
                if (taskCart.getTaskReadyRptNum() !=0){
                    isRpt = true;
                }
            }
        }


        //若车间任务未开工、未申请领料，则删除车间任务
        if (wkspTask.getOperationStatus() == 0 && wkspTask.getPickingStatus() == 0){
            wkspTaskMapper.deleteWkspTaskById(wkspTask.getId());
        } else if (wkspTask.getOperationStatus() == 0 && wkspTask.getPickingStatus() == 1) {
            //若车间任务未开工、已申请领料，则删除车间任务、删除领料入库信息
            List<PickInfo> pickInfos = pickInfoMapper.selectPickInfoByWkspTaskId(wkspTask.getId());
            for (PickInfo pickInfo : pickInfos) {
                pickInfoMapper.deletePickInfoById(pickInfo.getId());
            }

            wkspTaskMapper.deleteWkspTaskById(wkspTask.getId());
        } else if (wkspTask.getOperationStatus() == 0 && wkspTask.getPickingStatus() == 2) {
            //若车间任务未开工、已领料，则删除车间任务、返回原料
            revokePickService.revokeMtr(wkspTask);

            wkspTaskMapper.deleteWkspTaskById(wkspTask.getId());
        } else if (wkspTask.getOperationStatus() == 1 && wkspTask.getPickingStatus() == 2 && isRpt == false) {
            //若车间任务生产中、已领料、任务卡未报工,则删除车间任务、任务卡、返回原料
            for (TaskCart taskCart : taskCarts) {
                taskCartMapper.deleteTaskCartByTaskCardId(taskCart.getTaskCardId());
            }

            revokePickService.revokeMtr(wkspTask);

            wkspTaskMapper.deleteWkspTaskById(wkspTask.getId());
        } else if (wkspTask.getOperationStatus() == 1 && wkspTask.getPickingStatus() == 2 && isRpt == true) {
            //若车间任务生产中、已领料、任务卡报工,则更改车间任务、任务卡状态为已取消
            for (TaskCart taskCart : taskCarts) {
                taskCart.setStatus(3L);
                taskCartMapper.updateTaskCart(taskCart);
            }

            wkspTask.setOperationStatus(3L);
            wkspTaskMapper.updateWkspTask(wkspTask);
        }


        return AjaxResult.success("撤回成功!");
    }
}
